package mbsl.system;

import java.util.prefs.Preferences;

import org.eclipse.swt.widgets.Display;

import mbsl.extensions.Loader;
import mbsl.extensions.MissingDependencyException;
import mbsl.main.LoadingScreen;
import mbsl.main.MainController;
import mbsl.storage.Database;

/**
 * The Core is the class which controls the program.
 * 
 * It was conceived as a singleton, but since only the logger is static, one could in theory run several cores in one VM, and
 * each one would control a different instance of the application.
 * @author aschj
 *
 */
public class Core {
	private static Logger logger = new Logger(Core.class);
	/**
	 * Provides access to the core package's text bundle.
	 */
	public static TextProvider tp = new TextProvider();
	
	private MainController mMainWindowController;
	private Database mDataBase;
	private Loader mExtensionLoader;
	private Display mDisplay;
	private LoadingScreen mLoadingScreen;
	
	/**
	 * The Core constructor
	 * 
	 * This method will not return until the application is closed.
	 */
	public Core() {
		logger.info("Starting Core");

		logger.info("Starting Display");
		
		mDisplay = new Display();
		
		mLoadingScreen = new LoadingScreen(mDisplay);
		
		mLoadingScreen.open();

		logger.info("Starting Database");
		try {
			mDataBase = new Database();
		} catch (MissingDependencyException e) {
			System.out.println(e.getText());
			return;
		}
		
		mLoadingScreen.setValue(25);
		
		logger.info("Loading UI");

		mMainWindowController = new MainController(this);

		mLoadingScreen.setValue(50);

		logger.info("Loading Extensions");
		mExtensionLoader = new Loader(this);
		
		if (mDataBase != null)
			mDataBase.start();

		mLoadingScreen.setValue(75);
		
		mExtensionLoader.start();
		
		mLoadingScreen.setValue(100);
		
		logger.info("Spawning UI");
		// Leaves control to the main window controller, where it stays until the main window is disposed
		mMainWindowController.start();
		// after which it returns here, so:
		close();
	}
	public Logger getLogger(Class<?> pClass) {
		return new Logger(pClass);
	}
	/** Returns a Preferences instance in the node "mbsl" */
	public static Preferences getPreferences() {
		return Preferences.userRoot().node("mbsl");
	}
	
	public Display getDisplay() {
		return mDisplay;
	}
	
	public Database getDatabase() {
		return mDataBase;
	}
	
	public MainController getMainController() {
		return mMainWindowController;
	}
	
	public void closeLoadingScreen() {
		if (mLoadingScreen != null) {
			mLoadingScreen.close();
			
			mLoadingScreen = null;
		}
	}
	
	private void close() {
		logger.info("Sending Shutdown to Extensions");
		mExtensionLoader.shutDown();
		
		logger.info("Releasing Display");
		mDisplay.dispose();
		
		logger.info("Stopping Database");
		mDataBase.close();
		
		logger.info("Shutting Down");
	}
}
